// 封装验证码组件
// Captcha: 全自动取反任何计算机的图灵测试（验证码）
/*
  1.验证码实质上是图片
  2.验证码可以被点击，可能存在看不清的情况
  3.验证码的获取方式
    a.验证码是有后端产生且由后端验证
    b.两种获取展示方式
      1）后端直接输出图片------->将图片地址给到img标签的src属性
      2）后端输出图片的编码字符串----->给到img标签的src属性
      无论是那种方法获取，用法一致
  4.验证码在做前后端分离的项目时，后端除了给验证码意外，
    还会给到一个key值（token），请注意key值与验证码是唯一 一一对应匹配的
    key值后续需要在提交用户输入的验证码的时候一并提交给服务端，
    服务端在验证验证码的时候还会验证key值，
    所以前端需要负责key值的临时存储（时机：获取之后，提交之前）
  5.需要考虑验证码的尺寸大小问题：
      在使用Captcha组件的时候，通过props传值
  6.key若存储在当前组件的state中，会存在key值被覆盖的情况，因此，是谁调用谁存储（即存在父组件中）
      子传父：子将验证码的key值传给父（父传递一个方法来获取key值（getKey）,子调用）
  7.在离开页面的时候要做清理的操作（清除请求）
    a.先定义source（CancelToken的source方法）
      source = axios.CancelToken.source()
    b. 如果是get请求，参数以对象的形式位于第二个实参
       如果是post请求,参数则是第三个实参
       cancelToken: this.source.token
    c. 在componentWillUnmount中取消请求
        this.source.cancel()

 */
// 使用方法：
//  a. 需要在使用验证码的组件中去 导入 并 使用验证码组件
//  b. 该组件接收三个props属性
//      w: 验证码宽度，可选，有默认值120
//      h: 验证码高度，可选，有默认值40
//      setKey: 用于让父组件获取并保存key值的方法，必须传递，且父必须定义
import React, { Component } from 'react';
import axios from "axios"
class Captcha extends Component {
  state = {}
  // CancelToken
  // CancelToken = axios.CancelToken
  source = axios.CancelToken.source()
  render() {
    // 灵活获取尺寸大小
    let w = this.props.w || 120
    let h = this.props.h || 40
    return (
      <>
        <img src={this.state.img} alt="点击刷新验证码" onClick={this.loadCaptcha.bind(this)} width={w} height={h}/>
      </>
    );
  }
  componentDidMount() {
    // 首次请求验证码
    this.loadCaptcha()
  }
  loadCaptcha() {
    axios.get("https://reactapi.iynn.cn/captcha/api/math", {
        cancelToken: this.source.token
      })
      .then((res) => {
        this.setState({
          // 验证码的key值
          key: res.data.key,
          // 验证码图片的编码字符串
          img: res.data.img
        })
        // 父想拿到key值，传递一个方法来获取key值
        this.props.setKey(res.data.key)
      })
      // 捕获promise异常，否则会有取消提示
      .catch(function(thrown) {})
  }
  componentWillUnmount() {
    // 取消请求
    this.source.cancel()
  }
}

export default Captcha;
